perm filename CHAR.MSS[WHT,LSP] blob sn#754052 filedate 1984-05-12 generic text, type T, neo UTF8
@Part[Char, Root = "CLM.MSS"]
@Comment{Chapter of Common Lisp Manual.  Copyright 1984 Guy L. Steele Jr.⎇


@MyChapter[Characters]

@clisp provides a character data type; objects of this type
represent printed symbols such as letters.

In general, characters in @clisp are not true objects; @f[eq] cannot
be counted upon to operate on them reliably.  In particular,
it is possible that the expression
@Lisp
(let ((x z) (y z)) (eq x y))
@Endlisp
may be false rather than true, if the value of @f[z] is a character.
@Rationale{This odd breakdown of @f[eq] in the case of characters
allows the implementor enough design freedom to produce exceptionally
efficient code on conventional architectures.  In this respect the
treatment of characters exactly parallels that of numbers, as described
in chapter @ref[NUMBER].⎇
If two objects are to be compared for ``identity,'' but either might be
a character, then the predicate @Funref[eql] is probably appropriate.

@Section[Character Attributes]

Every character has three attributes: code, bits, and font.
The code attribute is intended to distinguish among the printed glyphs
and formatting functions for characters.  The bits attribute allows extra
flags to be associated with a character.  The font attribute permits
a specification of the style of the glyphs (such as italics).

@Defcon[Var {char-code-limit⎇]
The value of @f[char-code-limit] is a non-negative
integer that is the upper exclusive bound on values produced
by the function @Funref[char-code], which returns the @i[code] component
of a given character; that is, the values returned by @f[char-code]
are non-negative and strictly less than the value of
@f[char-code-limit].
@Enddefcon

@Defcon[Var {char-font-limit⎇]
The value of @f[char-font-limit] is a non-negative
integer that is the upper exclusive bound on values produced
by the function @Funref[char-font], which returns the @i[font] component
of a given character; that is, the values returned by @f[char-font]
are non-negative and strictly less than the value of
@f[char-font-limit].
@Implementation{No @clisp implementation is required to support
non-zero font attributes; if it does not, then @f[char-font-limit]
should be @f[1].⎇
@Enddefcon

@Defcon[Var {char-bits-limit⎇]
The value of @f[char-bits-limit] is a non-negative
integer that is the upper exclusive bound on values produced
by the function @Funref[char-bits], which returns the @i[bits] component
of a given character; that is, the values returned by @f[char-bits]
are non-negative and strictly less than the value of
@f[char-bits-limit].  Note that the value of @f[char-bits-limit]
will be a power of two.
@Implementation{No @clisp implementation is required to support
non-zero bits attributes; if it does not, then @f[char-bits-limit]
should be @f[1].⎇
@Enddefcon

@Section[Predicates on Characters]

The predicate @Funref[characterp] may be used to determine
whether any @xlisp object is a character object.

@Defun[Fun {standard-char-p⎇, Args {@i[char]⎇]
The argument @i[char] must be a character object.
@f[standard-char-p] is true if the argument is a ``standard character,''
that is, an object of type @f[standard-char].

Note that any character with a non-zero @i[bits] or
@i[font] attribute is non-standard.
@Enddefun

@Defun[Fun {graphic-char-p⎇, Args {@i[char]⎇]
The argument @i[char] must be a character object.
@f[graphic-char-p] is true if the argument is a ``graphic'' (printing)
character, and false if it is a ``non-graphic'' (formatting or control)
character.  Graphic characters have a standard textual representation
as a single glyph, such as @f[A] or @f[*] or @f[=].
By convention, the space character is considered to be graphic.
Of the standard characters
all but @f[#\Newline] are graphic.
The semi-standard characters
@f[#\Backspace], @f[#\Tab], @f[#\Rubout], @f[#\Linefeed], @f[#\Return],
and @f[#\Page] are not graphic.

Programs may assume that
graphic characters of font 0 are all of the same width
when printed, for example, for purposes of columnar
formatting.  (This does not prohibit the use of a variable-pitch font
as font 0, but merely implies that every implementation of @clisp
must provide @i[some] mode of operation in which font 0 is
a fixed-pitch font.)
Portable programs should assume that, in general,
non-graphic characters and characters of
other fonts may be of varying widths.

Any character with a non-zero bits attribute is non-graphic.
@Enddefun

@Defun[Fun {string-char-p⎇, Args {@i[char]⎇]
The argument @i[char] must be a character object.
@f[string-char-p] is true if @i[char] can be stored into
a string, and otherwise is false.
Any character that satisfies @f[standard-char-p]
also satisfies @f[string-char-p]; others may also.
@Enddefun

@Defun[Fun {alpha-char-p⎇, Args {@i[char]⎇]
The argument @i[char] must be a character object.
@f[alpha-char-p] is true if the argument is an alphabetic
character, and otherwise is false.

If a character is alphabetic, then it is perforce graphic.
Therefore any character with a non-zero bits attribute cannot be alphabetic.
Whether a character is alphabetic may depend on its font number.

Of the standard characters (as defined by @f[standard-char-p]),
the letters @f[A] through @f[Z] and @f[a] through @f[z] are alphabetic.
@Enddefun

@Defun[Fun {upper-case-p⎇, Args {@i[char]⎇]
@Defun1[Fun {lower-case-p⎇, Args {@i[char]⎇]
@Defun1[Fun {both-case-p⎇, Args {@i[char]⎇]
The argument @i[char] must be a character object.

@f[upper-case-p] is true if the argument is an uppercase
character, and otherwise is false.

@f[lower-case-p] is true if the argument is a lowercase
character, and otherwise is false.

@f[both-case-p] is true if the argument is an uppercase character and
there is a corresponding lowercase character (which can be obtained
using @Funref[char-downcase]), or if the argument is a lowercase character and
there is a corresponding uppercase character (which can be obtained
using @Funref[char-upcase]).

If a character is either uppercase or lowercase, it is necessarily
alphabetic (and therefore is graphic, and therefore has a zero @i[bits]
attribute).  However, it is permissible in theory for an alphabetic
character to be neither uppercase nor lowercase (in a non-Roman font,
for example).

Of the standard characters (as defined by @f[standard-char-p]),
the letters @f[A] through @f[Z] are uppercase and @f[a]
through @f[z] are lowercase.
@Enddefun

@Defun[Fun {digit-char-p⎇, Args {@i[char] @optional (@i[radix] 10)⎇]
The argument @i[char] must be a character object,
and @i[radix] must be a non-negative integer.
If @i[char] is not a digit of the radix
specified by @i[radix], then @f[digit-char-p] is
false; otherwise it returns
a non-negative integer that is the ``weight'' of @i[char] in that radix.

Digits are necessarily graphic characters.

Of the standard characters (as defined by @f[standard-char-p]),
the characters @f[0] through @f[9], @f[A] through @f[Z],
and @f[a] through @f[z]
are digits.  The weights of @f[0] through @f[9] are the integers 0 through 9,
and of @f[A] through @f[Z] (and also @f[a] through @f[z]) are 10 through 35.
@f[digit-char-p] returns the weight for one of these digits if and only if
its weight is strictly less than @i[radix].  Thus, for example,
the digits for radix 16 are
@lisp
0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F
@endlisp

Here is an example of the use of @f[digit-char-p]:
@Lisp
(defun convert-string-to-integer (str @optional (radix 10))
  "Given a digit string and optional radix, return an integer."
  (do ((j 0 (+ j 1))
       (n 0 (+ (* n radix)
	       (or (digit-char-p (char str j) radix)
		   (error "Bad radix-@tilde@;D digit: @tilde@;C"
			  radix
			  (char str j))))))
      ((= j (length str)) n)))
@Endlisp
@Enddefun

@Defun[Fun {alphanumericp⎇, Args {@i[char]⎇]
The argument @i[char] must be a character object.
@f[alphanumericp] is true if @i[char] is either alphabetic
or numeric.  By definition,
@Lisp
(alphanumericp x)
   @EQ (or (alpha-char-p x) (not (null (digit-char-p x))))
@Endlisp
Alphanumeric characters are therefore necessarily graphic
(as defined by @Funref[graphic-char-p]).

Of the standard characters (as defined by @f[standard-char-p]),
the characters @f[0] through @f[9], @f[A] through @f[Z],
and @f[a] through @f[z] are alphanumeric.
@Enddefun

@Defun[Fun {char=⎇, Funlabel {char#&M⎇, Args {@i[character] @rest @i[more-characters]⎇]
@Defun1[Fun {char/=⎇, Funlabel {char#O#&M⎇, Args {@i[character] @rest @i[more-characters]⎇]
@Defun1[Fun {char<⎇, Funlabel {char#&L⎇, Args {@i[character] @rest @i[more-characters]⎇]
@Defun1[Fun {char>⎇, Funlabel {char#&N⎇, Args {@i[character] @rest @i[more-characters]⎇]
@Defun1[Fun {char<=⎇, Funlabel {char#&L#&M⎇, Args {@i[character] @rest @i[more-characters]⎇]
@Defun1[Fun {char>=⎇, Funlabel {char#&N#&M⎇, Args {@i[character] @rest @i[more-characters]⎇]
The arguments must all be character objects.
These functions compare the objects using the implementation-dependent
total ordering on characters, in a manner analogous to numeric
comparisons by @Xfunref[X {=⎇, L {#&M⎇] and related functions.

The total ordering on characters is guaranteed to have the following
properties:
@Begin[Itemize]
@Begin[Multiple]
The standard alphanumeric characters obey the following partial ordering:
@Lisp
A<B<C<D<E<F<G<H<I<J<K<L<M<N<O<P<Q<R<S<T<U<V<W<X<Y<Z
a<b<c<d<e<f<g<h<i<j<k<l<m<n<o<p<q<r<s<t<u<v<w<x<y<z
0<1<2<3<4<5<6<7<8<9
@i[either] 9<A @i[or] Z<0
@i[either] 9<a @i[or] z<0
@Endlisp
This implies that alphabetic ordering holds within each case (upper and
lower), and that the digits as a group
are not interleaved with letters.  However, the ordering
or possible interleaving of
uppercase letters and lowercase letters is unspecified.
(Note that both the @c[ascii] and the @c[ebcdic] character sets
conform to this specification.  As it happens, neither ordering
interleaves uppercase and lowercase letters:
in the @c[ascii] ordering, @f[9<A] and @f[Z<a],
whereas in the @c[ebcdic] ordering @f[z<A] and @f[Z<0].)
@End[Multiple]

If two characters have the same bits and font attributes,
then their ordering by @f[char<] is consistent with the numerical
ordering by the predicate @Xfunref[X {<⎇, L {#&L⎇] on their code attributes.

If two characters differ in any attribute (code, bits, or font), then they
are different.
@End[Itemize]
The total ordering is not necessarily the same as the total
ordering on the integers produced by applying @Funref[char-int] to the
characters (although it is a reasonable implementation technique to
use that ordering).

While alphabetic characters of a given case must be
properly ordered, they need not be contiguous; thus @f[(char<= #\a x
#\z)] is @i[not] a valid way of determining whether or not @f[x] is a
lowercase letter.  That is why a separate
@Funref[lower-case-p] predicate is provided.

@lisp
(char= #\d #\d) @r[is true.]
(char/= #\d #\d) @r[is false.]
(char= #\d #\x) @r[is false.]
(char/= #\d #\x) @r[is true.]
(char= #\d #\D) @r[is false.]
(char/= #\d #\D) @r[is true.]
(char= #\d #\d #\d #\d) @r[is true.]
(char/= #\d #\d #\d #\d) @r[is false.]
(char= #\d #\d #\x #\d) @r[is false.]
(char/= #\d #\d #\x #\d) @r[is false.]
(char= #\d #\y #\x #\c) @r[is false.]
(char/= #\d #\y #\x #\c) @r[is true.]
(char= #\d #\c #\d) @r[is false.]
(char/= #\d #\c #\d) @r[is false.]
(char< #\d #\x) @r[is true.]
(char<= #\d #\x) @r[is true.]
(char< #\d #\d) @r[is false.]
(char<= #\d #\d) @r[is true.]
(char< #\a #\e #\y #\z) @r[is true.]
(char<= #\a #\e #\y #\z) @r[is true.]
(char< #\a #\e #\e #\y) @r[is false.]
(char<= #\a #\e #\e #\y) @r[is true.]
(char> #\e #\d) @r[is true.]
(char>= #\e #\d) @r[is true.]
(char> #\d #\c #\b #\a) @r[is true.]
(char>= #\d #\c #\b #\a) @r[is true.]
(char> #\d #\d #\c #\a) @r[is false.]
(char>= #\d #\d #\c #\a) @r[is true.]
(char> #\e #\d #\b #\c #\a) @r[is false.]
(char>= #\e #\d #\b #\c #\a) @r[is false.]
(char> #\z #\A) @r[may be true or false.]
(char> #\Z #\a) @r[may be true or false.]
@Endlisp

There is no requirement that @f[(eq c1 c2)] be true merely because
@f[(char= c1 c2)] is true.  While @f[eq] may distinguish two character
objects that @f[char=] does not, it is distinguishing them not
as @i[characters], but in some sense on the basis of a lower-level
implementation characteristic.
(Of course, if @f[(eq c1 c2)] is true,
then one may expect @f[(char= c1 c2)] to be true.)
However, @Funref[eql] and @Funref[equal]
compare character objects in the same
way that @f[char=] does.
@Enddefun

@Defun[Fun {char-equal⎇, Args {@i[character] @rest @i[more-characters]⎇]
@Defun1[Fun {char-not-equal⎇, Args {@i[character] @rest @i[more-characters]⎇]
@Defun1[Fun {char-lessp⎇, Args {@i[character] @rest @i[more-characters]⎇]
@Defun1[Fun {char-greaterp⎇, Args {@i[character] @rest @i[more-characters]⎇]
@Defun1[Fun {char-not-greaterp⎇, Args {@i[character] @rest @i[more-characters]⎇]
@Defun1[Fun {char-not-lessp⎇, Args {@i[character] @rest @i[more-characters]⎇]
The predicate @f[char-equal] is like @f[char=], and similarly
for the others, except according to a different ordering such that
differences of bits attributes and case are ignored,
and font information is taken into account in an implementation-dependent
manner.  For the standard characters, the ordering is such that
@f[A=a], @f[B=b], and so on, up to @f[Z=z], and furthermore either
@f[9<A] or @f[Z<0].
For example:
@lisp
(char-equal #\A #\a) @r[is true]
(char= #\A #\a) @r[is false]
(char-equal #\A #\Control-A) @r[is true]
@Endlisp
The ordering may depend on the font information. For example, an implementation
might decree that @f[(char-equal #\p #\@i[p])] be true, but that
@f[(char-equal #\p #\@Sail[π])] be false (where @f[#\@sail[π]] is a
lowercase @f[p] in some font).  Assuming italics to be in font 1
and the Greek alphabet in font 2, this is the same as saying that
@f[(char-equal #0\p #1\p)] may be true and at the same time
@f[(char-equal #0\p #2\p)] may be false.
@Enddefun

@Section[Character Construction and Selection]

These functions may be used to extract attributes of a character
and to construct new characters.

@Defun[Fun {char-code⎇, Args {@i[char]⎇]
The argument @i[char] must be a character object.
@f[char-code] returns the @i[code] attribute of the character object;
this will be a non-negative integer less than the (normal) value of
the variable @Conref[char-code-limit].
@Enddefun

@Defun[Fun {char-bits⎇, Args {@i[char]⎇]
The argument @i[char] must be a character object.
@f[char-bits] returns the @i[bits] attribute of the character object;
this will be a non-negative integer less than the (normal) value of
the variable @Conref[char-bits-limit].
@Enddefun

@Defun[Fun {char-font⎇, Args {@i[char]⎇]
The argument @i[char] must be a character object.
@f[char-font] returns the @i[font] attribute of the character object;
this will be a non-negative integer less than the (normal) value of
the variable @Conref[char-font-limit].
@Enddefun

@Defun[Fun {code-char⎇, Args {@i[code] @optional (@i[bits] 0) (@i[font] 0)⎇]
All three arguments must be non-negative integers.
If it is possible in the implementation to construct a character
object whose code attribute is @i[code], whose bits attribute is @i[bits],
and whose font attribute is @i[font], then such an object is returned;
otherwise @false is returned.

For any integers @i[c], @i[b], and @i[f], if @f[(code-char @i[c] @i[b] @i[f])]
is not @false then
@Lisp
(char-code (code-char @i[c] @i[b] @i[f])) @EV @i[c]
(char-bits (code-char @i[c] @i[b] @i[f])) @EV @i[b]
(char-font (code-char @i[c] @i[b] @i[f])) @EV @i[f]
@Endlisp
If the font and bits attributes of a character object @i[x] are zero,
then it is the case that
@Lisp
(char= (code-char (char-code c)) c)
@Endlisp
is true.
@Enddefun

@Defun[Fun {make-char⎇, Args {@i[char] @optional (@i[bits] 0) (@i[font] 0)⎇]
The argument @i[char] must be a character,
and @i[bits] and @i[font] must be non-negative integers.
If it is possible in the implementation to construct a character
object whose code attribute is the same as
the code attribute of @i[char],
whose bits attribute is @i[bits],
and whose font attribute is @i[font], then such an object is returned;
otherwise @false is returned.

If @i[bits] and @i[font] are zero, then @f[make-char] cannot fail.
This implies that for every character object one can ``turn off''
its bits and font attributes.
@Enddefun

@Section[Character Conversions]


These functions perform various transformations on characters,
including case conversions.

@Defun[Fun {character⎇, Args {@i[object]⎇]
The function @f[character] coerces its argument to be a character
if possible; see @Funref[coerce].
@Lisp
(character x) @EQ (coerce x 'character)
@Endlisp
@Enddefun


@Defun[Fun {char-upcase⎇, Args {@i[char]⎇]
@Defun1[Fun {char-downcase⎇, Args {@i[char]⎇]
The argument @i[char] must be a character object.
@f[char-upcase] attempts to convert its argument to an uppercase
equivalent; @f[char-downcase] attempts to convert its argument
to a lowercase equivalent.

@f[char-upcase] returns a character object with the same font
and bits attributes as @i[char], but with possibly a different code
attribute.  If the code is different from @i[char]'s, then the predicate
@Funref[lower-case-p] is true of @i[char], and @Funref[upper-case-p]
is true of the result character.  Moreover, if @f[(char= (char-upcase x) x)]
is @i[not] true, then it is true that
@Lisp
(char= (char-downcase (char-upcase x)) x)
@Endlisp

Similarly,
@f[char-downcase] returns a character object with the same font
and bits attributes as @i[char], but with possibly a different code
attribute.  If the code is different from @i[char]'s, then the predicate
@Funref[upper-case-p] is true of @i[char], and @Funref[lower-case-p]
is true of the result character.  Moreover, if @f[(char= (char-downcase x) x)]
is @i[not] true, then it is true that
@Lisp
(char= (char-upcase (char-downcase x)) x)
@Endlisp
Note that the action of @f[char-upcase] and @f[char-downcase] may
depend on the bits and font attribute of the character.  In particular,
they have no effect on a character with a non-zero bits attribute,
because such characters are by definition not alphabetic.
See @Funref[alpha-char-p].
@Enddefun

@Defun[Fun {digit-char⎇, Args {@i[weight] @optional (@i[radix] 10) (@i[font] 0)⎇]
All arguments must be integers.  @f[digit-char]
determines whether or not it is possible to construct
a character object
whose font attribute is @i[font], and whose @i[code] is such that the
result character has the weight @i[weight] when considered as
a digit of the radix @i[radix] (see the predicate @Funref[digit-char-p]).
It returns such a character if that is possible, and otherwise returns @false.

@f[digit-char] cannot return @false if @i[font] is zero,
@i[radix] is between 2 and 36 inclusive, and @i[weight] is non-negative
and less than @i[radix].

If more than one character object can encode
such a weight in the given radix, one will be chosen consistently
by any given implementation; moreover, among the standard characters,
uppercase letters are preferred to lowercase letters.
For example:
@lisp
(digit-char 7) @EV #\7
(digit-char 12) @EV @false
(digit-char 12 16) @EV #\C          ;@r[not] #\c
(digit-char 6 2) @EV @false
(digit-char 1 2) @EV #\1
@Endlisp
Note that no argument is provided for specifying the @i[bits] component
of the returned character, because a digit cannot have a non-zero
@i[bits] component.  The reasoning is that every digit is graphic
(see @Funref[digit-char-p]) and no graphic character has a non-zero
@i[bits] component (see @Funref[graphic-char-p]).
@Enddefun

@Defun[Fun {char-int⎇, Args {@i[char]⎇]
The argument @i[char] must be a character object.
@f[char-int] returns a non-negative integer encoding the character object.

If the font and bits attributes of @i[char] are zero, then
@f[char-int] returns the same integer @f[char-code] would.
Also,
@Lisp
(char= c1 c2) @EQ (= (char-int c1) (char-int c2))
@Endlisp
for characters @f[c1] and @i[c2].

This function is provided primarily for the purpose of hashing characters.
@Enddefun

@Defun[Fun {int-char⎇, Args {@i[integer]⎇]
The argument must be a non-negative integer.
@f[int-char] returns a character object @f[c] such that
@f[(char-int c)] is equal to @i[integer], if possible; otherwise
@f[int-char] returns false.
@Enddefun


@Defun[Fun {char-name⎇, Args {@i[char]⎇]
The argument @i[char] must be a character object.
If the character has a name, then that name (a string) is returned;
otherwise @false is returned.  All characters that have
zero font and bits attributes and that are non-graphic
(do not satisfy the predicate @Funref[graphic-char-p]) have names.
Graphic characters may or may not have names.

The standard newline and space characters have the respective
names @f[Newline] and @f[Space].
The semi-standard characters have the names
@f[Tab], @f[Page], @f[Rubout], @f[Linefeed], @f[Return], and @F[Backspace].

Characters that have names can be notated as @f[#\] followed
by the name.  (See section @ref[SHARP-SIGN-MACRO-CHARACTER-SECTION].)
Although the name may be written in any case,
it is stylish to capitalize it thus: @f[#\Space].

@f[char-name] will only locate ``simple'' character names;
it will not construct names such as @f[Control-Space] on the
basis of the character's bits attribute.
@Enddefun

@Defun[Fun {name-char⎇, Args {@i[name]⎇]
The argument @f[name] must be an object coerceable to a string
as if by the function @Funref[string].
If the name is the same as the name of a character object
(as determined by @Funref[string-equal]), that object
is returned; otherwise @false is returned.
@Enddefun

@Section[Character Control-Bit Functions]

@clisp provides explicit names for four bits of the bits attribute:
@i[Control], @i[Meta], @i[Hyper], and @i[Super].  The following
definitions are provided for manipulating these.
Each @clisp implementation provides these functions for compatibility,
even if it does not support any or all of the bits named below.

@Defcon[Var {char-control-bit⎇]
@Defcon1[Var {char-meta-bit⎇]
@Defcon1[Var {char-super-bit⎇]
@Defcon1[Var {char-hyper-bit⎇]
The values of these named constants are the ``weights'' (as integers) for
the four named control bits.  The weight of the control bit is @f[1];
of the meta bit, @f[2]; of the super bit, @f[4]; and of the hyper bit, @f[8].

If a given implementation of @clisp does not support a particular bit,
then the corresponding constant is zero instead.
@Enddefcon

@Defun[Fun {char-bit⎇, Args {@i[char] @i[name]⎇]
@f[char-bit] takes a character object @i[char] and the name of a bit,
and returns non-@false if the bit of that name is set in @i[char],
or @false if the bit is not set in @i[char].
For example:
@lisp
(char-bit #\Control-X @Kwd[control]) @EV @i[true]
@endlisp
Valid values for @i[name]
are implementation-dependent, but typically are @Kwd[control],
@Kwd[meta], @Kwd[hyper], and @Kwd[super].
It is an error to give @f[char-bit] the name of a bit not supported
by the implementation.

If the argument @i[char] is specified by a form that is a @i[place] form
acceptable to @Macref[setf],
then @f[setf] may be used with @f[char-bit]
to modify a bit of the character stored in that
@i[place].
The effect is to perform a @Funref[set-char-bit] operation
and then store the result back into the @i[place].
@Enddefun

@Defun[Fun {set-char-bit⎇, Args {@i[char] @i[name] @i[newvalue]⎇]
@f[char-bit] takes a character object @i[char], the name of a bit,
and a flag.  A character is returned that is just like @i[char]
except that the named bit is set or reset according to whether
@i[newvalue] is non-@false or @false.
Valid values for @i[name]
are implementation-dependent, but typically are @Kwd[control],
@Kwd[meta], @Kwd[hyper], and @Kwd[super].
For example:
@lisp
(set-char-bit #\X @Kwd[control] t) @EV #\Control-X
(set-char-bit #\Control-X @Kwd[control] t) @EV #\Control-X
(set-char-bit #\Control-X @Kwd[control] @false) @EV #\X
@Endlisp
@Enddefun